Floyd算法
核心语句
for(int k=0;k<n;k++){
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
if(cost[i][j]>cost[i][k]+cost[k][j])
cost[i][j]=cost[i][k]+cost[k][j];
}
}
}
完整代码
//floyd
//复杂度O(N^2)
#include<iostream>
#include<cstdio>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1e3+50;
int mapp[MAXN][MAXN];
int N,M;
int main()
{
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
if(i==j){
mapp[i][j]=0;
}else{
mapp[i][j]=INF;
}
}
}
int u,v,w;
for(int i=1;i<=M;i++){
scanf("%d%d%d",&u,&v,&w);
mapp[u][v]=w;
}
for(int k=1;k<=N;k++){
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
if(mapp[i][j]>mapp[i][k]+mapp[k][j]){
mapp[i][j]=mapp[i][k]+mapp[k][j];
}
}
}
}
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
printf("%10d",mapp[i][j]);
}
printf("\n");
}
return 0;
}
Bellman-Ford 算法
https://blog.csdn.net/liangzhaoyang1/article/details/51344742
Bellman-ford算法是求含负权图的单源最短路径算法,效率很低,但代码很容易写。即进行持续地松弛(原文是这么写的,为什么要叫松弛,争议很大),每次松弛把每条边都更新一下,若n-1次松弛后还能更新,则说明图中有负环,无法得出结果,否则就成功完成。Bellman-ford算法有一个小优化:每次松弛先设一个标识flag,初值为FALSE,若有边更新则赋值为TRUE,最终如果还是FALSE则直接成功退出。
for(int k=1;k<=n-1;k++) //遍历点的次数
{
check=0;//用check检查是否进行下一轮次的操作
for(int i=1;i<=m;i++) //遍历边的次数
{
if(dis[v[i]]>dis[u[i]]+w[i]) //如果从u到v的距离能够通过w这条边压缩路径 就要进行松弛操作
{
dis[v[i]]=dis[u[i]]+w[i];
check=1;
}
}
if(check==0)break;
}
Bellman-Ford算法浪费了许多时间做没有必要的松弛,
SPFA算法
在 Bellman-ford 算法的基础上加上一个队列优化,减少了冗余的松弛操作,是一种高效的最短路算法。
变量:
int s,t; //s为起点,t为终点
bool visit[ ]
int dis[t] //从s到t的最短路径
int cnt[ ] //如果某个点进入队列的次数大于等于 n,则存在负权回路,其中 n 为图的顶点数。
【初始化】
dist数组全部初始化为inf,visit数组为未访问
dist[s]=0
【松弛操作】
读取队头顶点u,将u出队,标记已访问,将与u相连的顶点v进行松弛操作,更新值,并且,如果v不在队列中,入队,标记已访问,如果在队列中就不用再入队,这样不断从队列中取出顶点来进行松弛操作。
以此循环,直到队空为止就完成了单源最短路的求解。
【负边】:如果某个点进入队列的次数大于等于 n,则存在负权回路,其中 n 为图的顶点数。
【模板】
//spafa
//复杂度O(KE)
#include<iostream>
#include<cstdio>
#include<queue>
#include<queue>
#include<cstring>
using namespace std;
const int MAXN=1010;
const int INF=0x3f3f3f3f;
struct edge{
int v,cost;
edge(int _v,int _cost):v(_v),cost(_cost){}
};
vector<edge>E[MAXN];
void add_edge(int u,int v,int w)
{
E[u].push_back(edge(v,w));
}
bool vis[MAXN];
int cnt[MAXN];
int dist[MAXN];
bool spfa(int start,int n)
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++){
dist[i]=INF;
}
vis[start]=true;
dist[start]=0;
queue<int>que;
while(!que.empty()){
que.pop();
}
que.push(start);
memset(cnt,0,sizeof(cnt));
cnt[start]=1;
while(!que.empty()){
int u=que.front();
que.pop();
vis[u]=false;
for(int i=0;i<E[u].size();i++){
int v=E[u][i].v;
if(dist[v]>dist[u]+E[u][i].cost){
dist[v]=dist[u]+E[u][i].cost;
if(!vis[v]){
vis[v]=true;
que.push(v);
if(++cnt[v]>n){
return false;
}
}
}
}
}
return true;
}
int main()
{
return 0;
}